/**
 * TraitTree.java
 * @author Team KARP
 * 
 * This trait tree will store the "master list" of stock traits and also all of the organisms so that
 * the user can copy traits from them.
 * 
 */
package protovitae.data;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import protovitae.engine.DrawableOrganism;

public class TraitTree implements MutableTreeNode {

    private ArrayList<MutableTreeNode> children;
    private ArrayList<DrawableOrganism> organisms;
    private MutableTreeNode parent = null;

    public TraitTree(ArrayList<DrawableOrganism> organisms) {
        children = new ArrayList();
        this.organisms = organisms;

        //Example for cosmetic purposes. Override once population exists...
        /*ConcreteGene example = new ConcreteGene(null); //Doesn't belong to an organisms
        example.setName("Example Stock Gene");
        children.add(example);*/
    }

    @Override
    public String toString() {
        return "All Traits";
    }

    /** Add to our list of stock traits **/
    public void addStockTrait(MutableTreeNode trait) {
        children.add(trait);
    }

    /** Clear the list of Stock traits for some reason **/
    public void clearStockTraits() {
        children.clear();
    }

    /** Remove an item from the list of stock traits **/
    public void removeStockTrait(ConcreteGene thetrait) {
        children.remove(thetrait);
    }

    /**
     * Returns the child <code>TreeNode</code> at index 
     * <code>childIndex</code>.
     */
    public TreeNode getChildAt(int childIndex) {
        if (childIndex >= children.size()) {
            return organisms.get(childIndex - children.size());
        }
        return children.get(childIndex);
    }

    /**
     * Returns the index of <code>node</code> in the receivers children.
     * If the receiver does not contain <code>node</code>, -1 will be
     * returned.
     */
    public int getIndex(TreeNode node) {
        int retval = children.indexOf(node);
        if (retval < 0) {
            retval = organisms.indexOf(node);
        }
        return retval;
    }

    public Gene getGene(String t){
        for(ConcreteOrganism co : organisms){
            for(Gene g : co.getGenome()){
                if(g.getName().equals(t)){
                    return g;
                }
            }
        }
      System.out.println("NO GENE FOUND");
      return null;
    }
    
    /**
     * Returns true if the receiver is a leaf.
     */
    public boolean isLeaf() {
        return (children.size() == 0) && (organisms.size() == 0);
    }

    /**
     * Returns the parent <code>TreeNode</code> of the receiver.
     */
    public TreeNode getParent() {
        return parent;
    }

    /**
     * Returns the number of children <code>TreeNode</code>s the receiver
     * contains.
     */
    public int getChildCount() {
        return children.size() + organisms.size();
    }

    /**
     * Returns true if the receiver allows children.
     */
    public boolean getAllowsChildren() {
        return true;
    }

    /** Adapter to make children() work with ArrayList's iterator **/
    public class Enumdapter implements Enumeration {

        Iterator stockitr, orgitr; //Internal iterator

        /** Creates a new instance of Enumdapter */
        public Enumdapter(Iterator sit, Iterator oit) {
            stockitr = sit;
            orgitr = oit;
        }

        public Object nextElement() {
            if (stockitr.hasNext()) {
                return stockitr.next();
            } else {
                return orgitr.next();
            }
        }

        public boolean hasMoreElements() {
            return orgitr.hasNext();
        }
    }

    /**
     * Returns the children of the receiver as an <code>Enumeration</code>.
     */
    public Enumeration children() {
        return new Enumdapter(children.iterator(), organisms.iterator());
    }

    /**
     * Sets the parent of the receiver to <code>newParent</code>.
     */
    public void setParent(MutableTreeNode newParent) {
        parent = newParent;
    }

    /**
     * Removes <code>node</code> from the receiver. <code>setParent</code>
     * will be messaged on <code>node</code>.
     */
    public void remove(MutableTreeNode node) {
        children.remove(node);
    }

    /**
     * Adds <code>child</code> to the receiver at <code>index</code>.
     * <code>child</code> will be messaged with <code>setParent</code>.
     */
    public void insert(MutableTreeNode child, int index) {
        children.add(index, child);
    }

    /**
     * Resets the user object of the receiver to <code>object</code>.
     */
    public void setUserObject(Object object) {
    //Erm.... This will always be the parent object, I'm not replacing it.
    }

    /**
     * Removes the child at <code>index</code> from the receiver.
     */
    public void remove(int index) {
        children.remove(index);
    }

    /**
     * Removes the receiver from its parent.
     */
    public void removeFromParent() {
    //We don't have a parent, so do nothing.
    }
}
